package com.feri.fitness.cs.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.feri.fitness.common.config.RedisKeyConfig;
import com.feri.fitness.common.config.RocketMQConfig;
import com.feri.fitness.common.dto.MoodAddDto;
import com.feri.fitness.common.dto.MoodRefwordDto;
import com.feri.fitness.common.dto.MqLevelMsg;
import com.feri.fitness.common.util.DateUtil;
import com.feri.fitness.common.vo.R;
import com.feri.fitness.cs.dao.MoodDao;
import com.feri.fitness.cs.dao.MoodMediaDao;
import com.feri.fitness.cs.domain.Mood;
import com.feri.fitness.cs.domain.MoodMedia;
import com.feri.fitness.cs.exception.MoodException;
import com.feri.fitness.cs.service.intf.MoodService;
import javax.annotation.Resource;
import com.feri.fitness.cs.util.RocketMqUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 千锋郑州Java学科欢迎你
 * @program: Fitness
 * @description: 业务接口实现层
 * @author: Feri
 * @create: 2023-01-12 08:59:28
 */
@Service
public class MoodServiceImpl implements MoodService{
    /**
    *注入持久层对象*/
    @Resource
    private MoodDao dao;
    @Resource
    private MoodMediaDao moodMediaDao;
    @Resource
    private StringRedisTemplate redisTemplate;

    @Transactional
    @Override
    public R save(MoodAddDto dto, int uid) {
        //1.校验
        if(dto!=null){
            //2.创建动态对象
            Mood mood=new Mood();
            BeanUtils.copyProperties(dto,mood);
            mood.init();
            mood.setUid(uid);
            //3.操作数据库
            if(dao.insert(mood)>0){
                //4.如果是图文动态或 视频动态 需要添加动态媒体表数据
                if(mood.getType()==2){
                    //图片
                    List<MoodMedia> list=new ArrayList<>();

                    for(String url:dto.getUrls()){
                        list.add(new MoodMedia(mood.getId(),url));
                    }
                    moodMediaDao.insertBatch(list);
                }else if(mood.getType()==3){
                    //视频
                    moodMediaDao.insert(new MoodMedia(mood.getId(),dto.getUrls()[0]));
                }
                //4.验证动态类型,给予对应的成长值
                int g=0;
                switch (dto.getType()){
                    case 1:g=5;break;
                    case 2:g=10;break;
                    case 3:g=20;break;
                }
                //5.发送MQ消息
                RocketMqUtil.send(RocketMQConfig.MQ_GROW, JSON.toJSONString(
                        new MqLevelMsg(uid,g,
                                "恭喜你，发布动态成功，给予奖励")));
                return R.ok();
            }
        }
        return R.fail();
    }

    @Override
    public R refword(MoodRefwordDto dto, int uid) {
        //1.验证
        if(dto!=null){
            //2.创建动态对象
            Mood mood=new Mood();
            mood.init();
            BeanUtils.copyProperties(dto,mood);

            mood.setUid(uid);
            //3.操作数据库
            if(dao.insert(mood)>0){
                //4.查询被转发的动态详情
                Mood m=dao.selectById(mood.getParentid());
                //5.查询被转发的动态的次数
                long num=dao.selectNum(m.getUid(), DateUtil.getNow());
                if(num<= 10 ){

                    //6.给予奖励 被转发的动态的用户
                    RocketMqUtil.send(RocketMQConfig.MQ_GROW, JSON.toJSONString(
                            new MqLevelMsg(m.getUid(),3,
                                    "你的动态今日被转发了，给予成长值奖励")));

                }
                return R.ok();
            }
        }
        return R.fail();
    }

    @Override
    public R queryHot() {
        //实际上应该是多表联查,这里懒省事写的单表
        QueryWrapper<Mood> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("looktype",1);
        queryWrapper.orderByDesc("ctime");

        return R.ok(dao.selectList(queryWrapper));
    }

    @Override
    public R queryFollow(int uid) {
        return R.ok(dao.selectFollow(uid));
    }

    @Override
    public R queryCity(String city) {
        //1.条件构造器
        QueryWrapper<Mood> wrapper=new QueryWrapper<>();
        wrapper.eq("address",city);
        wrapper.eq("looktype",1);
        wrapper.orderByDesc("ctime");
        return R.ok(dao.selectList(wrapper));
    }

    @Override
    public R query(int id) {
        //实际上应该是多表联查,这里懒省事写的单表
        //可以考虑缓存，减少数据库的查询
        //Redis 1.为啥使用  性能 2.如何选择数据类型 Hash 3.有效期 今天有效
        //存储今日访问的所有的动态 只要今天访问，就做缓存，有效期今日有效
        //1.验证缓存是否存在
        boolean h=redisTemplate.hasKey(RedisKeyConfig.KEY_MOOD);
        if(h){
            //2.验证是否存在当前这个动态
            if(redisTemplate.opsForHash().hasKey(RedisKeyConfig.KEY_MOOD,id)){
                //缓存命中
                return R.ok(redisTemplate.opsForHash().get(RedisKeyConfig.KEY_MOOD,id));
            }
        }
        //3.查询数据库
        QueryWrapper<Mood> wrapper=new QueryWrapper<>();
        wrapper.eq("id",id);
        wrapper.eq("flag",1);
        Mood mood=dao.selectOne(wrapper);
        //4.更新缓存
        redisTemplate.opsForHash().put(RedisKeyConfig.KEY_MOOD,id,mood);
        if(!h){
            //5.第一次 创建缓存的Hash需要 设置有效期
            redisTemplate.expire(RedisKeyConfig.KEY_MOOD,DateUtil.getSurplusSeconds(), TimeUnit.SECONDS);
        }
        return R.ok(mood);
    }

    @Transactional
    @Override
    public R del(int mid) throws MoodException {
        if(mid>0){
            if(dao.del(mid)>0){
                //保证数据同步  动态做的有缓存 直接操作
                //验证是否存在缓存
                if(redisTemplate.hasKey(RedisKeyConfig.KEY_MOOD)){
                    if(redisTemplate.opsForHash().delete(RedisKeyConfig.KEY_MOOD,mid)>0){
                        return R.ok();
                    }else {
                        throw new MoodException("Redis缓存更新失败，需要回滚");
                    }
                }
                return R.ok();
            }
        }
        return R.fail();
    }
}